#include "tcpconnection.h"
#include <boost/bind.hpp>

TcpConnection::TcpConnection(Service &service) :
    m_sock(service)
{

}

TcpConnection::~TcpConnection()
{

}

TcpConnection::Socket &TcpConnection::sock()
{
    return m_sock;
}

int TcpConnection::remoteEndpoint(std::string &host, unsigned short &port)
{
    ErrorCode ec;
    Endpoint ep;

    ep = m_sock.remote_endpoint(ec);

    if(ec){
        return ec.value();
    }

    host = ep.address().to_string();
    port = ep.port();

    return 0;
}

void TcpConnection::asyncRead(void *buf, size_t size,
               BOOST_ASIO_MOVE_ARG(Filter) f,
               BOOST_ASIO_MOVE_ARG(Completion) c)
{
    boost::asio::async_read
            (
                m_sock,
                boost::asio::buffer(buf, size),
                boost::bind
                (
                    &TcpConnection::isComplete,
                    this,
                    Filter(f),
                    _1,
                    _2
                ),
                boost::bind
                (
                    &TcpConnection::onComplete,
                    this,
                    Completion(c),
                    _1,
                    _2
                )
            );
}

void TcpConnection::asyncWrite(const void *buf, size_t size,
                BOOST_ASIO_MOVE_ARG(Filter) f,
                BOOST_ASIO_MOVE_ARG(Completion) c)
{
    boost::asio::async_write
            (
                m_sock,
                boost::asio::buffer(buf, size),
                boost::bind
                (
                    &TcpConnection::isComplete,
                    this,
                    Filter(f),
                    _1,
                    _2
                ),
                boost::bind
                (
                    &TcpConnection::onComplete,
                    this,
                    Completion(c),
                    _1,
                    _2
                )
            );
}

void TcpConnection::close()
{
    ErrorCode ec;

    m_sock.close(ec);
}

size_t TcpConnection::isComplete(Filter f, ErrorCode ec, size_t size)
{
    if(ec){
        return 0;
    }

    return f(size);
}

void TcpConnection::onComplete(Completion c, ErrorCode ec, size_t size)
{
    c(size, ec.value());
}
